﻿// -------------------------------------------------------------------------
//    @FileName         :    NFWorldWelfareDBData.cpp
//    @Author           :    gaoyi
//    @Date             :    2025-07-10
//    @Email			:    445267987@qq.com
//    @Module           :    NFWorldWelfareDBData
//
// -------------------------------------------------------------------------

#include "NFWorldWelfareDBData.h"

#include "NFWorldDataService.h"
#include "NFWorldWelfareMgr.h"
#include "NFWorldWelfareService.h"
#include "proto_svr_common.nanopb.h"
#include "NFComm/NFCore/NFServerTime.h"
#include "NFComm/NFPluginModule/NFRoute.h"
#include "NFServerComm/NFServerCommon/NFIServerMessageModule.h"

NFWorldWelfareDBData::NFWorldWelfareDBData()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode()) {
        CreateInit();
    }
    else {
        ResumeInit();
    }
}

NFWorldWelfareDBData::~NFWorldWelfareDBData()
{
}

int NFWorldWelfareDBData::CreateInit()
{
    m_bGSDirty = false;
    m_uiSynGSSec = 0;
    SetTimer(1000, 0, 0, 0, 0, 0);
    return 0;
}

int NFWorldWelfareDBData::ResumeInit()
{
    return 0;
}

int NFWorldWelfareDBData::OnTimer(int timeId, int callCount)
{
    Tick();
    return 0;
}

const WelfareDBWorldData* NFWorldWelfareDBData::GetWelfareDB() const
{
    return m_stData.get_m_stData_m_stWelfareDBWorldData();
}

const WelfareDBWorldDataConfig* NFWorldWelfareDBData::GetConfig() const
{
    auto pWelfareDB = GetWelfareDB();
    CHECK_NULL_RET_VAL(0, pWelfareDB, nullptr);

    return &pWelfareDB->m_stConfig;
}

WelfareDBWorldData* NFWorldWelfareDBData::GetWelfareDB()
{
    return m_stData.get_m_stData_m_stWelfareDBWorldData();
}

WelfareDBWorldDataConfig* NFWorldWelfareDBData::GetConfig()
{
    auto pWelfareDB = GetWelfareDB();
    CHECK_NULL_RET_VAL(0, pWelfareDB, nullptr);

    return &pWelfareDB->m_stConfig;
}

int NFWorldWelfareDBData::InitDBData()
{
    m_stData.init_which_m_stData(pbWorldData_m_stWelfareDBWorldData_tag);
    return 0;
}

int NFWorldWelfareDBData::Tick()
{
    if (!NFGlobalSystem::Instance()->GetGlobalPluginManager()->IsInited(NF_ST_WORLD_SERVER))
    {
        return 0;
    }

    if (NFGlobalSystem::Instance()->GetGlobalPluginManager()->IsServerStopping())
    {
        return 0;
    }

    WelfareDBWorldData* pWorldDBData = GetWelfareDB();
    CHECK_NULL(0, pWorldDBData);

    CheckOpenClose(pWorldDBData);

    CheckSyncToGameSvr(pWorldDBData);
    return 0;
}

int NFWorldWelfareDBData::CheckOpenClose(WelfareDBWorldData* pWorldDBData)
{
    int iRetCode = 0;
    CHECK_NULL(0, pWorldDBData);
    std::set<uint64_t> stSetOpenID;
    iRetCode = NFWorldWelfareMgr::Instance()->GetWorldDataOpenIDs(stSetOpenID);
    CHECK_ERR(0, iRetCode, "");

    for (auto it = pWorldDBData->m_astWelfareDBDataOne.begin(); it != pWorldDBData->m_astWelfareDBDataOne.end();)
    {
        WelfareDBWorldDataOne& stWelfareDBDataOne = it->second;
        if (stSetOpenID.find(stWelfareDBDataOne.m_ullWelfareID) == stSetOpenID.end())
        {
            LOG_INFO(0, "Del Welfare Data:{}", stWelfareDBDataOne.ShortDebugString());
            iRetCode = DelOneWelfareBefore(stWelfareDBDataOne);
            if (iRetCode != 0)
            {
                LOG_ERR(0, iRetCode, "DelOneWelfareBefore failed, retCode:{}", iRetCode);
            }
            it = pWorldDBData->m_astWelfareDBDataOne.erase(it);
            MarkDirty();
            continue;
        }
        else
        {
            stSetOpenID.erase(stWelfareDBDataOne.m_ullWelfareID);
        }
        ++it;
    }

    for (auto it = stSetOpenID.begin(); it != stSetOpenID.end(); ++it)
    {
        uint64_t ullWelfareID = *it;
        AddOneWelfare(pWorldDBData, ullWelfareID);
    }
    return 0;
}

int NFWorldWelfareDBData::AddOneWelfare(WelfareDBWorldData* pWorldDBData, uint64_t welfareID)
{
    CHECK_NULL(0, pWorldDBData);
    const NFWelfareConfOne* pConfOne = NFWorldWelfareMgr::Instance()->GetConf().FindConf(welfareID);
    CHECK_NULL_WF(0, pConfOne, "DelOneWelfareBefore failed, not find conf, id:{}", welfareID);

    if (!NFWorldWelfareService::IsHaveWorldData(pConfOne->GetWelfareConf()))
    {
        LOG_ERR(0, -1, "AddOneWelfare failed, not have world data, id:{}", welfareID);
        return 0;
    }

    if (pWorldDBData->m_astWelfareDBDataOne.full())
    {
        LOG_ERR(0, -1, "AddOneWelfare failed, m_astWelfareDBDataOne full, id:{}", welfareID);
        return -1;
    }

    if (pWorldDBData->m_astWelfareDBDataOne.find(welfareID) != pWorldDBData->m_astWelfareDBDataOne.end())
    {
        LOG_ERR(0, -1, "AddOneWelfare failed, m_astWelfareDBDataOne exist, id:{}", welfareID);
        return -1;
    }

    WelfareDBWorldDataOne stWelfareDBDataOneTemp;
    int iRetCode = InitOneWelfare(stWelfareDBDataOneTemp, pConfOne->GetWelfareConf());
    CHECK_ERR(0, iRetCode, "InitOneWelfare failed, retCode:{}", iRetCode);

    pWorldDBData->m_astWelfareDBDataOne[welfareID] = stWelfareDBDataOneTemp;

    LOG_INFO(0, "AddOneWelfare, data:{}", pWorldDBData->m_astWelfareDBDataOne[welfareID].ShortDebugString());
    MarkDirty();
    return 0;
}

int NFWorldWelfareDBData::InitOneWelfare(WelfareDBWorldDataOne& stWorldDBDataOne, const E_Welfare& stDesc, uint32_t uiUpdateUnixSec)
{
    stWorldDBDataOne.Init();
    stWorldDBDataOne.m_ullWelfareID = stDesc.m_welfareId;
    if (uiUpdateUnixSec == 0)
    {
        stWorldDBDataOne.m_uiLastUpdateUnixSec = NF_ADJUST_TIMENOW();
    }
    else
    {
        stWorldDBDataOne.m_uiLastUpdateUnixSec = uiUpdateUnixSec;
    }

    stWorldDBDataOne.m_dwActStartUnixSec = 0;
    switch (stDesc.m_type)
    {
        case WELFARE_TYPE_WORLD_COLLECT:
        {
            stWorldDBDataOne.m_stWelfareDBDataUnion.init_which_m_stData(WelfareDBWorldDataUnion_m_stWorldCollect_tag);
            break;
        }
        case WELFARE_TYPE_WORLD_VOTE_COLLECT:
        {
            stWorldDBDataOne.m_stWelfareDBDataUnion.init_which_m_stData(WelfareDBWorldDataUnion_m_stWorldVoteCollect_tag);
            break;
        }
        default:
        {
            CHECK_ERR(0, -1, "Err InitOneWelfare, WelfareID = %lu, enType = %d", stDesc.m_welfareId, stDesc.m_type);
            return -1;
        }
    }

    LOG_INFO(0, "InitOneWelfare, data:{}", stDesc.ShortDebugString());
    return 0;
}

int NFWorldWelfareDBData::DelOneWelfareBefore(WelfareDBWorldDataOne& stWelfareDBDataOne)
{
    const NFWelfareConfOne* pConfOne = NFWorldWelfareMgr::Instance()->GetConf().FindConf(stWelfareDBDataOne.m_ullWelfareID);
    CHECK_NULL_WF(0, pConfOne, "DelOneWelfareBefore failed, not find conf, id:{}", stWelfareDBDataOne.m_ullWelfareID);

    const E_Welfare& stDesc = pConfOne->GetWelfareConf();
    switch (stDesc.m_type)
    {
        default:
            break;
    }
    return 0;
}

void NFWorldWelfareDBData::MarkDirty()
{
    m_dwCurSeq++;
    m_bIsUrgentNeedSave = true;
    m_bGSDirty = true;
    auto pWorldDBData = GetWelfareDB();
    if (pWorldDBData)
    {
        pWorldDBData->m_ullVersion += 1;
    }
}

int NFWorldWelfareDBData::CheckSyncToGameSvr(WelfareDBWorldData* pWorldDBData, bool bForce)
{
    if (!bForce)
    {
        if (!m_bGSDirty)
        {
            return 0;
        }

        if (m_uiSynGSSec + 5 > NF_ADJUST_TIMENOW())
        {
            return 0;
        }
    }

    m_uiSynGSSec = NF_ADJUST_TIMENOW();
    SyncToGameSvr(pWorldDBData, 0, 0);
    m_bGSDirty = false;
    return 0;
}

int NFWorldWelfareDBData::GetWorldDBData(proto_ff::SSWorldWelfareSyncDBDataRes& res)
{
    WelfareDBWorldData* pWorldDBData = GetWelfareDB();
    CHECK_NULL(0, pWorldDBData);
    pWorldDBData->ToPb(res.mutable_m_stwelfaredbworlddata());
    res.set_m_isynctype(0);
    return 0;
}

int NFWorldWelfareDBData::SyncToGameSvr(WelfareDBWorldData* pWorldDBData, int iSvrID, int iSyncType)
{
    CHECK_NULL(0, pWorldDBData);

    proto_ff::SSWorldWelfareSyncDBDataRes res;
    pWorldDBData->ToPb(res.mutable_m_stwelfaredbworlddata());
    res.set_m_isynctype(iSyncType);

    if (iSvrID == 0)
    {
        FindModule<NFIServerMessageModule>()->SendMsgToLogicServer(NF_ST_WORLD_SERVER, LOCAL_ALL_ROUTE, SS_MSGID_WORLD, SS_SUB_MSGID_WORLD_WELFARE_SYNC_DBDATA, res);
    }
    else
    {
        FindModule<NFIServerMessageModule>()->SendMsgToLogicServer(NF_ST_WORLD_SERVER, iSvrID, SS_MSGID_WORLD, SS_SUB_MSGID_WORLD_WELFARE_SYNC_DBDATA, res);
    }
    return 0;
}
